/**
 *ListPool.java
 *@anthor Daniel Liu
 *2006-4-28 21:31:08
 **/
package org.lex.utils.pool;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class QueuePool<T> extends AbstractPool<T> {
	private BlockingQueue<T> pool = null;
	private int maxIdleNumber = DEFAULT_IDLE_NUMBER;
	private int activeCount = 0;

	public QueuePool() {
		this(null, DEFAULT_IDLE_NUMBER);
	}

	public QueuePool(int maxIdle) {
		this(null, maxIdle);
	}

	public QueuePool(ObjectFactory<T> factory) {
		this(factory, DEFAULT_IDLE_NUMBER);
	}

	public QueuePool(ObjectFactory<T> factory, int maxIdle) {
		super();
		this.pool = new LinkedBlockingQueue<T>();
		this.setFactory(factory);
		this.maxIdleNumber = maxIdle;
	}

	public T get() {
		assertOpen();
		assertFactory();
		T obj = null;
		while (null == obj) {
			if (0 != pool.size()) {
				try {
					obj = pool.take();
				} catch (InterruptedException e) {
					e.printStackTrace();
					obj = null;
				}
			} else
				obj = this.getFactory().create();

			if (null != obj) {
				getFactory().prepare(obj);
				if (false == getFactory().isReuseable(obj)) {
					getFactory().destroy(obj);
					obj = null;
				}
			}
		}
		this.activeCount++;
		return obj;
	}

	public void put(T obj) {
		assertOpen();
		assertFactory();
		if (false == getFactory().isReuseable(obj) || false == getFactory().clean(obj)) {
			// obj��������ʹ�û�������ʧ�ܣ��轫�����
			getFactory().destroy(obj);
			obj = null;
			activeCount--;
			return;
		}

		if (pool.size() >= maxIdleNumber)
			getFactory().destroy(obj);
		else
			pool.add(obj);
		activeCount--;
		return;
	}

	public void clear() {
		this.pool.clear();
	}

	public int getActiveCount() {
		return this.activeCount;
	}

	public int getPoolSize() {
		return this.pool.size() + this.activeCount;
	}
}
